package com.iflytek.uoamp.agent.monitor.mcagent;

import com.alibaba.fastjson.JSON;
import com.iflytek.uoamp.agent.common.constants.CommonConstants;
import com.iflytek.uoamp.agent.core.agentinterface.IAgent;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.MonitorItemConfig;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.MonitorPluginType;
import com.iflytek.uoamp.agent.core.sender.monitorsender.responseObj.AgentLog;
import com.iflytek.uoamp.agent.monitor.find.CMDExecuteWorker;
import com.iflytek.uoamp.agent.monitor.find.FinderThread;
import com.iflytek.uoamp.agent.monitor.find.GetAgentVersionTask;
import com.iflytek.uoamp.agent.monitor.job.MCAgentJobManager;
import com.iflytek.uoamp.agent.monitor.lib.CreateSender;
import com.iflytek.uoamp.agent.monitor.sender.MsgSendClient;
import com.iflytek.uoamp.agent.monitor.utils.ValidIP.ValidIP;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.log4j.Logger;

import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 
 * @ClassName: MCAgentMain
 * @Description: monitor启动模块
 * @author qinanyuan
 * @date 2017年3月23日 下午3:20:56
 */
public class MCAgentMain implements IAgent{
	private static MsgSendClient senderClient;
	private static Set<String> checkNames = new HashSet<String>();
	private static boolean isStartMonitor = false;
	private static boolean isStartAgent = false;
	private static List<MonitorItemConfig> monitorList = null;
	private static String LEVEL = "1";

	public static Set<String> getCheckNames() {
		return checkNames;
	}

	public static void setCheckNames(Set<String> checkNames) {
		MCAgentMain.checkNames = checkNames;
	}

	public static MsgSendClient getSenderClient() {
		return senderClient;
	}

	public static void setSenderClient(MsgSendClient senderClient) {
		MCAgentMain.senderClient = senderClient;
	}

	public static boolean isStartMonitor() {
		return isStartMonitor;
	}

	public static void setStartMonitor(boolean isStartMonitor) {
		MCAgentMain.isStartMonitor = isStartMonitor;
	}

	public static boolean isStartAgent() {
		return isStartAgent;
	}

	public static void setStartAgent(boolean isStartAgent) {
		MCAgentMain.isStartAgent = isStartAgent;
	}

	public static List<MonitorItemConfig> getMonitorList() {
		return monitorList;
	}

	public static void setMonitorList(List<MonitorItemConfig> monitorList) {
		MCAgentMain.monitorList = monitorList;
	}


	@Override
	public void init() {
		// 执行初始化工作
		MCinitializer iniCinitializer = new MCinitializer();
		try {
			iniCinitializer.initial();
		} catch (Exception e) {
			Logger.getRootLogger().error("iniCinitializer init failed, throw " + ExceptionUtils.getMessage(e));
		}
		// 初始化cmd执行worker线程池
		CMDExecuteWorker.getInstance().init();
		
	}

	@Override
	public void start() {
		//创建monitor发送客户端
		startSenderClient();
		//启动monitor模块各功能线程
		startMonitorThread();
		//发送agent启动日志到server
		sendStartLog();
	}
	
	
	/**
	 * <code>Agent版本监控任务</code>
	 * @author zhuwei
	 * @date 2016/11/18 16:29
	 */
	private static void getAgentVersionTask(){
		try {
            ScheduledExecutorService ses= Executors.newScheduledThreadPool(1);
            GetAgentVersionTask gat = new GetAgentVersionTask();
            ses.scheduleWithFixedDelay(gat, 0, CommonConstants.GETVERSION_INTERVAL, TimeUnit.MINUTES);
            Logger.getRootLogger().info("Init GetAgentVersionTask success...");
        } catch (Exception e) {
        	Logger.getRootLogger().error("getAgentVersionTask method failed, throw " + ExceptionUtils.getMessage(e));
        }
	}

		    
	@Override
	public String getPropertiy() {
		return LEVEL;
	}

	public static String setToString() {
		if (checkNames == null) {
			return "";
		}

		StringBuffer temp = new StringBuffer();
		for (String cur : checkNames) {
			temp.append(cur + ",");
		}
		Logger.getRootLogger().info("my cur set is " + temp.toString());
		return temp.toString();
	}

	private static AgentLog getStartLog(SimpleDateFormat format) {
		MCAgentConfig mcAgentConfig = MCAgentConfig.getInstance();
		Properties props = System.getProperties();
		String osName = props.getProperty("os.name");
		AgentLog log = new AgentLog();
		Map<String ,String > headers = new HashMap<String, String>();
		headers.put(CommonConstant.KEY_OSNAME, osName);
		headers.put(CommonConstant.KEY_STATUS, CommonConstant.VAL_STATUS_SCCEED);
		headers.put(CommonConstant.KEY_EVENTTYPE, CommonConstant.VAL_EVENTTYPE_RESTART);
		String localIp = mcAgentConfig.getMonitoredPointIp();
		headers.put(CommonConstant.KEY_LOCALIP, null == localIp ? CommonConstant.VAL_NULL : localIp);
		headers.put(CommonConstant.KEY_HOSTROOMNAME, mcAgentConfig.getEngineRoomName());
		headers.put("sinner", CommonConstant.VAL_NULL);
		headers.put("dinner", CommonConstant.VAL_NULL);
		headers.put(CommonConstant.KEY_VERSION, mcAgentConfig.getVersion());
		headers.put(CommonConstant.KEY_CPNAME, CommonConstant.ComponentMCAgent.NAME);
		headers.put(CommonConstant.KEY_CTM, format.format(new Date()));
		log.setHeaders(headers);
		return log;
	}

	/**
	 * init need monitor item
	 * */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static List<MonitorItemConfig> initMonitorData() {
		try {
			Logger.getRootLogger().info("MCAgentManager start init ItemData");
			MonitorPluginType monitorPluginType = new MonitorPluginType(MCAgentConfig.getInstance().getMonitoredPointIp(), "checklocal", null);
			Object result = null;
			if (MCAgentMain.senderClient.getConfig().isUseHttp()) {
				result = MCAgentMain.senderClient.sendByHttp(monitorPluginType);
				List list = JSON.parseObject(result.toString(), List.class);
				List<MonitorItemConfig> monitorItems = new LinkedList<MonitorItemConfig>();
				for (Object cur : list) {
					monitorItems.add(JSON.parseObject(cur.toString(), MonitorItemConfig.class));
				}
				return monitorItems;
			} else {
				result = MCAgentMain.senderClient.sendBySafe(monitorPluginType);
				Logger.getRootLogger().info("initMonitorData ==========>" + JSON.toJSONString(result));
				if (!(result instanceof List)) {
					return null;
				}
				return (List<MonitorItemConfig>) result;
			}
		} catch (Exception e) {
			Logger.getRootLogger().error(e.getMessage(), e);
			return null;
		}
	}

	public void startSenderClient(){
		SimpleDateFormat format = new SimpleDateFormat(CommonConstant.KEY_DATETIMEFORMAT);
		Date st = new Date();
		if (MCAgentConfig.getInstance().isAutoDetectLocalIp()) {
			// 使用Sigar探测本地网卡ip
			ValidIP mcip = new ValidIP(MCAgentConfig.getInstance().getMonitoredPointIp());
			if (!mcip.isOK() && !StringUtils.isEmpty(mcip.guessIP())) {
				Logger.getRootLogger().info("IP 可能填写错误"+ MCAgentConfig.getInstance().getMonitoredPointIp() + " change to " + mcip.guessIP());
				MCAgentConfig.getInstance().setMonitoredPointIp(mcip.guessIP());
			}
		} else {
			Logger.getRootLogger().info("auto detect local ip switch is off.");
		}

		String monitoredPointIp = MCAgentConfig.getInstance().getMonitoredPointIp();
		if (null == monitoredPointIp || monitoredPointIp.isEmpty()) {
			Logger.getRootLogger().error("i can't get ip,so stop agent!!");
			return;
		}
		// SendClient对象创建Factory
		CreateSender factory = new CreateSender();
		senderClient = new MsgSendClient(factory);
		// 新启动单独的线程轮询检测conf/msgSender.properties中配置的MCServer是否存活，使用ping实现
		senderClient.start();
	}

	public void startMonitorThread(){
		//执行Agent版本监控任务
		getAgentVersionTask();
		// 此时有可能还没有连接上MCServer,应该整成当MCServer连接成功时触发执行initMonitorData方法,
		monitorList = initMonitorData();
		FinderThread finderThread = new FinderThread();
		finderThread.setName("Auto find thread");
		finderThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			public void uncaughtException(Thread t, Throwable e) {
				Logger.getRootLogger().error("agent 捕获到uncaughtException!!!!!! The Exception is ====>" + e.getMessage());
			}
		});
		// 启动自动发现线程
		finderThread.start();
		// 启动监控结果发送线程
		new Thread(MonitorResultSender.getInstance(), "MonitorResultSender Thread").start();
	}

	public void sendStartLog(){
		SimpleDateFormat format = new SimpleDateFormat(CommonConstant.KEY_DATETIMEFORMAT);
		Date st = new Date();
		AgentLog log = getStartLog(format);
		Map<String ,String > headers = new HashMap<String, String>();
		headers.put(CommonConstant.KEY_STM, format.format(st));

		Date endDateTime = new Date();
		headers.put(CommonConstant.KEY_ETM, format.format(endDateTime));
		headers.put(CommonConstant.KEY_UTM, String.valueOf(endDateTime.getTime() - st.getTime()));
		log.setHeaders(headers);
		MCAgentLog mcAgent = new MCAgentLog(log);

		// 发送启动日志到MCServer端
		if (MCAgentMain.senderClient.getConfig().isUseHttp()) {
			MCAgentMain.senderClient.sendByHttp(mcAgent);
		} else {
			senderClient.sendBySafe(mcAgent);
		}

		isStartAgent = true;

		if (monitorList != null && monitorList.size() != 0) {
			for (MonitorItemConfig cur : monitorList) {
				checkNames.add(cur.getServerDesc());
			}
			//执行监控项任务
			try {
				MCAgentJobManager.startJob(monitorList);
			} catch (Exception e) {
				Logger.getRootLogger().error("MCAgentJobManager startJob fail! The Exception is ====>" + e.getMessage());
			}
			isStartMonitor = true;
		} else {
			Logger.getRootLogger().info("can't get any monitor item on start!");
		}
	}

}
